from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext.webapp import template
from google.appengine.ext import db
import os

from html import CheckBox, DropDown, MultiSelect #importing the html wrappers.
import validate #import validation
import tables
import main
import datetime
import staticInits 
import cgi #for escaping html chars in forms
import re


class AdvSearch(webapp.RequestHandler):
    '''Class for Advanced Search'''
    
    def __init__(self):
        #DB CALLS
        #building dictionaries, keyed with name attributes which are gauranteed unique to each entry
        (self.majors, self.languages, self.specializations, self.courses, self.profs) = (dict(), dict(), dict(), dict(), dict())
        #building dictionaries, keyed with name attributes which are gauranteed unique to each entry
        self.majors = [row.name for row in tables.Major.all().order('name')]
        self.languages = [row.name for row in tables.Language.all().order('name')]
        self.specializations = [row.name for row in tables.Specialization.all().order('name')]
        self.courses = [row.name for row in tables.Course.all().order('name')]
        self.profs = [row.firstName + " " + row.lastName for row in tables.Instructor.all().order('firstName').order('lastName')]
        
        #default searchtype is ta
        self.searchType = 'ta'

        self.currentState = tables.AppState.get_by_key_name('currentState')
        self.currentSemester = self.currentState.semester
        
        self.semesters = dict()
        for semester in db.GqlQuery("SELECT * FROM Semester"): self.semesters[str(semester)] = semester 
        
        
        self.origForm = dict()
        self.origForm['major'] = DropDown(self.majors, name = "Major")
        self.origForm['english'] = DropDown(["Yes", "No"], name = "Native English")
        self.origForm['language'] = DropDown(self.languages, name = "Language")
        self.origForm['specialization'] = DropDown(self.specializations, name = "Specialization")
        self.origForm['qualification'] = DropDown(self.courses, name = "Qualifications")
        self.origForm['prevassigned'] = DropDown(self.courses, name = "Previously Assigned")
        self.origForm['professors'] = DropDown(self.profs, name="Professors")
        self.origForm['assigned'] = DropDown(self.courses, name="Assigned")
        self.origForm['numTas'] = ''   
        
        self.DEFAULT_OPTION = "--make selection--"
    
    def get(self):
        '''Renders the template when URL is accessed'''
        
        (self.majors, self.languages, self.specializations, self.courses, self.profs) = (dict(), dict(), dict(), dict(), dict())
        #building dictionaries, keyed with name attributes which are gauranteed unique to each entry
        self.majors = [row.name for row in tables.Major.all().order('name')]
        self.languages = [row.name for row in tables.Language.all().order('name')]
        self.specializations = [row.name for row in tables.Specialization.all().order('name')]
        self.courses = [row.name for row in tables.Course.all().order('name')]
        self.profs = [row.firstName + " " + row.lastName for row in tables.Instructor.all().order('firstName').order('lastName')]
        
        self.searchSemester = self.currentSemester
        
        query = tables.Ta.all().filter("submitted =", True).filter('semester =', self.searchSemester).order('firstName')
        self.renderTemplate(self.origForm, query)
        
    def post(self):
        """Validates the form submit. If nothing was selected or inputted, return all the TAs or Classes depending on what was searched"""
        
        searchType = cgi.escape(self.request.get('searchType'))

        self.searchSemester = self.semesters[self.request.get('semesters')]

        error = ""
        query = None
        
        #TA searching
        major = "" if self.request.get('Major') == self.DEFAULT_OPTION else self.request.get('Major')
        nativeEnglish = "" if self.request.get('Native English') == self.DEFAULT_OPTION else self.request.get('Native English')
        language = "" if self.request.get('Language') == self.DEFAULT_OPTION else self.request.get('Language')
        specialization = "" if self.request.get('Specialization') == self.DEFAULT_OPTION else self.request.get('Specialization')
        qualification = "" if self.request.get('Qualifications') == self.DEFAULT_OPTION else self.request.get('Qualifications')
        prevAssigned = "" if self.request.get('Previously Assigned') == self.DEFAULT_OPTION else self.request.get('Previously Assigned')
        semester = "" if self.request.get('semesters') == self.DEFAULT_OPTION else self.request.get('semesters')
        
        professor = "" if self.request.get('Professors') == self.DEFAULT_OPTION else self.request.get('Professors')
        courseName = "" if self.request.get('Assigned') == self.DEFAULT_OPTION else self.request.get('Assigned')        
        numTas = cgi.escape(self.request.get('numTAs'))
        
        if searchType == "class":
            #Make sure to change the search type
            self.searchType = "class"
            #need to validate that the number of TAs inputted is a valid number
            
            query = tables.Section.all().order('uniqueNumber')
            if numTas :
                assert(numTas)
                if validate.validateNumTas(numTas) :
                    query.filter('numTas =', int(numTas))
                    if professor:
                        #get the right professor
                        professor = professor.split(" ")
                        instructorInstance = db.GqlQuery("SELECT * FROM Instructor WHERE firstName = :1 AND lastName = :2", professor[0], professor[1] ).get()
                        query.filter("instructor =", instructorInstance) 
                    if courseName:
                        courseInstance = db.GqlQuery("SELECT * FROM Course WHERE name = :1", courseName).get()
                        query.filter("course =", courseInstance)
                    if semester:                    
                        queryCopy = [item for item in query]
                        query = []
                        for copy in queryCopy:
                            if copy.semester.__str__() == semester:
                                query.append(copy)
                else:
                    error = "Validation failed. TAs needed must be a 1 digit number"
            else :
                assert( not numTas)
                if professor:
                    #get the right professor
                    professor = professor.split(" ")
                    instructorInstance = db.GqlQuery("SELECT * FROM Instructor WHERE firstName = :1 AND lastName = :2", professor[0], professor[1] ).get()
                    query.filter("instructor =", instructorInstance) 
                if courseName:
                    courseInstance = db.GqlQuery("SELECT * FROM Course WHERE name = :1", courseName).get()
                    query.filter("course =", courseInstance)
                if semester:                    
                    queryCopy = [item for item in query]
                    query = []
                    for copy in queryCopy:
                        if copy.semester.__str__() == semester:
                            query.append(copy)
                    
        elif searchType == "ta":
            self.searchType = "ta"
            query = tables.Ta.all()
            query = query.filter("submitted =", True)
            query = query.order('firstName')
            if nativeEnglish:
                #nativeEnglish gets me Yes/No but I need True/False
                nativeEnglish = True if nativeEnglish == "Yes" else False
                query.filter("nativeEnglish =", nativeEnglish)
            if major:
                majorInstance = db.GqlQuery("SELECT * FROM Major WHERE name = :1", major).get()
                query.filter("major =", majorInstance)
            if specialization:
                #make a copy of the query in order to filter correctly
                queryCopy = [item for item in query]
                query = []
                for copy in queryCopy:
                    for taSpecialization in copy.taSpecializations:
                        #print taSpecialization.specialization.name
                        #found = False
                        if taSpecialization.specialization.name == specialization:
                            query.append(copy)
                            #found = True
                        #print found
                    #didn't find the specialization, remove the TA by keeping the ones without the EID in the list
                    #if not found:
                        #query = query.filter("eid !=", copy.eid)
            if prevAssigned:
                queryCopy = [item for item in query]
                query = []
                for copy in queryCopy:
                    for taHistory in copy.taTaHistory:
                        if taHistory.taHistory.name == prevAssigned:
                            query.append(copy)
            if qualification:
                queryCopy = [item for item in query]
                query = []
                for copy in queryCopy:
                    for taQualification in copy.taQualifications:
                        if taQualification.qualification.name == qualification:
                            query.append(copy)
            if language:
                queryCopy = [item for item in query]
                query = []
                for copy in queryCopy:
                    for taLanguage in copy.taLanguages:
                        if taLanguage.language.name == language:
                            query.append(copy)
            if semester:
                queryCopy = [item for item in query]
                query = []
                for copy in queryCopy:
                    #print "Copy Semester is:", copy.semester.__str__()
                    #print "Semester is:", semester
                    if copy.semester.__str__() == semester:
                        #print "Equality True"
                        query.append(copy)
        
        #make this mess stickaaaaaay
        self.postForm = dict()
        self.postForm['major'] = DropDown(self.majors, name = "Major", selected = self.request.get('Major'))
        self.postForm['english'] = DropDown(["Yes", "No"], name = "Native English", selected = self.request.get('Native English'))
        self.postForm['language'] = DropDown(self.languages, name = "Language", selected = self.request.get('Language'))
        self.postForm['specialization'] = DropDown(self.specializations, name = "Specialization", selected = self.request.get('Specialization'))
        self.postForm['qualification'] = DropDown(self.courses, name = "Qualifications", selected = self.request.get('Qualifications'))
        self.postForm['prevassigned'] = DropDown(self.courses, name = "Previously Assigned", selected = self.request.get('Previously Assigned'))
        self.postForm['professors'] = DropDown(self.profs, name="Professors", selected = self.request.get('Professors'))
        self.postForm['assigned'] = DropDown(self.courses, name="Assigned", selected = self.request.get('Assigned'))        
        self.postForm['numTas'] = numTas
        
        
        self.renderTemplate(self.postForm, query, error)

    def renderTemplate(self, form, results = None, message=""):
        '''Renders the template file advSearch.html'''
        
        #setting up template dictionary
        
        if message:
            results = None
        
        if not results and not message:
            message = "No results found with given search criteria"
            
        templateValues = {
            'field' : form['major'],
            'specialization' : form['specialization'],
            'nativeEnglish' : form['english'],
            'assigned' : form['assigned'],
            'qualifications' : form['qualification'],
            'previouslyAssigned' : form['prevassigned'],
            'languages' : form['language'],
            'profs' : form['professors'],
            'results' : results,
            'searchType' : self.searchType,
            'numTas' : form['numTas'], 
            'semesters': DropDown(options=self.semesters.keys(), name = "semesters", selected = str(self.searchSemester), defaultOptionPresent = False), #for choosing 'view'
            'message': message,
        }
        
        #telling it to use the template
        path = os.path.join(os.path.dirname(__file__), 'advSearch.html')
        self.response.out.write(template.render(path, templateValues))

application = webapp.WSGIApplication([('/admin/advSearch', AdvSearch)], debug=True)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()
